package com.foundersoftware.commons.organization.util;


import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import java.util.Properties;

/**
 * This class can be used for remote access to the JNDI tree.
 * @author Adrian Price
 */
public final class JNDIUtils {
    // WFE EJBs all refer to their data source by this environment name.
    public static final String EJB_DATA_SOURCE =
        "java:comp/env/jdbc/TxDataSource";
    // This is the default data source for JBoss.
    public static final String DEFAULT_DATA_SOURCE = WFEConfig.getProperty("datasource","java:/MySQLDS");

    public static final String INITIAL_CONTEXT_FACTORY = WFEConfig.getProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");

    public static final String PROVIDER_URL =WFEConfig.getProperty("java.naming.provider.url", "jnp://localhost:1099");

    public static final String URL_PKG_PREFIXES = WFEConfig.getProperty("java.naming.factory.url.pkgs",null);

    // Do not instantiate this class.
    private JNDIUtils() {
    }

    /**
     * This method can be used from a J2EE server.
     * @return Context
     * @throws javax.naming.NamingException
     */
    public static InitialContext getInitialContext() throws NamingException {
        return getInitialContext(null, null, null);
    }

    /**
     * This method allows access to different URLs, but with the default
     * username.
     * @param url Server URL.
     * @return A JNDI InitialContext object.
     * @throws javax.naming.NamingException
     */
    public static InitialContext getInitialContext(String url)
        throws NamingException {

        return getInitialContext(url, null, null);
    }

    /**
     * This method is used on the server when a new username is needed for the
     * JNDI context.
     * @param username
     * @param credentials
     * @return Context
     * @throws javax.naming.NamingException
     */
    public static InitialContext getInitialContext(String username,
        Object credentials) throws NamingException {

        return getInitialContext(null, username, credentials);
    }

    /**
     * This method allows client code to specify URL and credentials with which
     * to connect.
     * @param url
     * @param username
     * @param credentials
     * @return A InitialContext object.
     * @throws javax.naming.NamingException
     */
    public static InitialContext getInitialContext(String url, String username,
        Object credentials) throws NamingException {

        // TODO: ensure AS-specific configuration in jndi.properties
        //-----now do it!
        if (url == null && username == null){
          Properties props = new Properties();
          props.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
          props.put(Context.PROVIDER_URL, PROVIDER_URL);
          if(URL_PKG_PREFIXES != null) {
              props.put(Context.URL_PKG_PREFIXES, URL_PKG_PREFIXES);
          }
          return new InitialContext(props);
        }

        Hashtable<String,Object> h = new Hashtable<String,Object>();

        if (url != null)
            h.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
            h.put(Context.PROVIDER_URL, url);
            if(URL_PKG_PREFIXES != null) {
                h.put(Context.URL_PKG_PREFIXES, URL_PKG_PREFIXES);
            }
        if (username != null) {
            h.put(Context.SECURITY_PRINCIPAL, username);

            if (credentials != null)
                h.put(Context.SECURITY_CREDENTIALS, credentials);
        }

        return new InitialContext(h);
    }

    /**
     * This method returns a DataSource object from JNDI.
     * @param name Name of the DataSource object
     * @param ctx JNDI Context.
     * @return DataSource object from JNDI
     * @exception javax.naming.NamingException
     */
    public static DataSource getDataSource(String name, Context ctx)
        throws NamingException {

        return (DataSource)ctx.lookup(name);
    }

    /**
     * This method returns a DataSource object from JNDI. This method will open
     * and close a temporary JNDI context.
     * @param name Name of the DataSource object
     * @return DataSource object from JNDI
     * @exception javax.naming.NamingException
     */
    public static DataSource getDataSource(String name) throws NamingException {
        Context ctx = getInitialContext();
        try {
            return getDataSource(name, ctx);
        } finally {
            ctx.close();
        }
    }
}
